﻿//-----------------------------------------------------------------------
// <copyright file="TestExcludedLinePrefix.cs" company="Anthony Steele">
// This source forms part of the DuplicateFinder utility
// Hosted at http://www.codeplex.com/DuplicateFinder
//
// This source is available under the terms of the Microsoft Public License (Ms-PL)
// See http://duplicatefinder.codeplex.com/license
// All other rights reserved.
// </copyright>
//-----------------------------------------------------------------------

namespace DuplicateFinder.TestLibrary
{
    using System.IO;

    using NUnit.Framework;

    /// <summary>
    /// Test excluding laines based on prefix
    /// </summary>
    [TestFixture]
    public class TestExcludedLinePrefix
    {
        /// <summary>
        /// Test data - simulates the contents of a file
        /// </summary>
        private const string InputText1 =
@"import foo;
import bar;
import fish;
import wibble;
import spon;

some different text 1234abc

foo
bar
fish
wibble
spon";

        /// <summary>
        /// Test data - simulates the contents of a file
        /// </summary>
        private const string InputText2 =
@"import foo;
import bar;
import fish;
import wibble;
import spon;

some different text 5678zyz

foo
bar
fish
wibble
spon";

        /// <summary>
        /// Test finding dups in the two files, without exclusions
        /// </summary>
        [Test]
        public void WithoutExclusionTest()
        {
            DuplicateFinderTester tester = new DuplicateFinderTester();
            ReadAndProcessTwoStreams(tester);

            TestDefaultResult(tester);
        }

        /// <summary>
        /// Test finding dups in the two files, with excusions that dont matter
        /// </summary>
        [Test]
        public void WithNoMatchingExclusionTest()
        {
            DuplicateFinderTester tester = new DuplicateFinderTester();
            DuplicateFinderLib.DuplicateFinderEngine finder = tester.Process;

            // none of these match what's in the texts
            // so should have no effect
            finder.AddIgnoredLinePrefix("ex1");
            finder.AddIgnoredLinePrefix("ex2");
            finder.AddIgnoredLinePrefix("ex3");
            finder.AddIgnoredLinePrefix("ex4");

            ReadAndProcessTwoStreams(tester);
            TestDefaultResult(tester);
        }

        /// <summary>
        /// Test finding dups in the two files, with exclusions
        /// </summary>
        [Test]
        public void WithExclusionTest()
        {
            DuplicateFinderTester tester = new DuplicateFinderTester();
            DuplicateFinderLib.DuplicateFinderEngine finder = tester.Process;

            // ignore lines that start with "import"
            // so the first duplicate is supressed
            // which we'd want if our "import" statements were the same across files
            finder.AddIgnoredLinePrefix("import");

            ReadAndProcessTwoStreams(tester);

            // only 1 duplicate found
            Assert.AreEqual(1, tester.DuplicateCount);
            Assert.AreEqual(5, tester.LastDuplicateLength);
        }

        /// <summary>
        /// Test finding dups in the two files, with more specific exclusions
        /// </summary>
        [Test]
        public void WithSpecificExclusionTest()
        {
            DuplicateFinderTester tester = new DuplicateFinderTester();
            DuplicateFinderLib.DuplicateFinderEngine finder = tester.Process;
            finder.DuplicateThreshold = 4;

            // if it's not the first line
            // it doesn't get excluded
            finder.AddIgnoredLinePrefix("import bar");
            finder.AddIgnoredLinePrefix("bar");

            ReadAndProcessTwoStreams(tester);

            // 2 duplicates found
            TestDefaultResult(tester);
        }

        /// <summary>
        /// Test finding dups in the two files, with exclusions
        /// that match in the middle
        /// </summary>
        [Test]
        public void WithMidExclusionTest()
        {
            DuplicateFinderTester tester = new DuplicateFinderTester();
            DuplicateFinderLib.DuplicateFinderEngine finder = tester.Process;
            finder.DuplicateThreshold = 4;

            // ignore lines that start with "import foo" and "foo"
            // should find duplicates in the lines after that
            finder.AddIgnoredLinePrefix("import foo");
            finder.AddIgnoredLinePrefix("foo");

            ReadAndProcessTwoStreams(tester);

            // 2 duplicates found
            Assert.AreEqual(2, tester.DuplicateCount);
            Assert.AreEqual(4, tester.LastDuplicateLength);

            Assert.AreEqual(5, tester.MaxDuplicateLength);
            Assert.AreEqual(2, tester.MaxDuplicateInstanceCount);
        }

        #region helpers

        /// <summary>
        /// Check that the default result occured
        /// </summary>
        /// <param name="tester">The tester to inspect</param>
        private static void TestDefaultResult(BaseDuplicateFinderTester tester)
        {
            // 2 duplicates 
            Assert.AreEqual(2, tester.DuplicateCount);
            Assert.AreEqual(5, tester.LastDuplicateLength);

            Assert.AreEqual(6, tester.MaxDuplicateLength);
            Assert.AreEqual(2, tester.MaxDuplicateInstanceCount);
        }

        /// <summary>
        /// Process the two input texts
        /// </summary>
        /// <param name="tester">The tester to act upon</param>
        private static void ReadAndProcessTwoStreams(DuplicateFinderTester tester)
        {
            StringReader reader1 = new StringReader(InputText1);
            StringReader reader2 = new StringReader(InputText2);

            DuplicateFinderLib.DuplicateFinderEngine finder = tester.Process;

            finder.ProcessText(reader1, "reader1");
            finder.ProcessText(reader2, "reader2");

            finder.FindDuplicates();
        }

        #endregion
    }
}

